﻿namespace ImageProcessing.Forms
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

    /// <summary>
    /// enum value for operation cmb
    /// </summary>
    public enum CmbValues
    {
        /// <summary>
        /// add two images
        /// </summary>
        And,

        /// <summary>
        /// sum two images
        /// </summary>
        Sum,

        /// <summary>
        /// sub two images
        /// </summary>
        Sub,

        /// <summary>
        /// or two images
        /// </summary>
        Or,

        /// <summary>
        /// product two images
        /// </summary>
        Product,

        /// <summary>
        /// xor two iamge
        /// </summary>
        Xor,

        /// <summary>
        /// Nand two images
        /// </summary>
        NAnd,

        /// <summary>
        /// nor two images
        /// </summary>
        Nor,

        /// <summary>
        /// Xnor operation
        /// </summary>
        Xnor,

        /// <summary>
        /// if image1 then image2
        /// </summary>
        Implies,

        /// <summary>
        /// image1 to image2
        /// </summary>
        Image1IffImage2,

        /// <summary>
        /// no choice
        /// </summary>
        Non
    }

    /// <summary>
    /// form calculation operation 
    /// </summary>
    public partial class CalculationForm : Form
    {
        /// <summary>
        /// image 1
        /// </summary>
        private DImage image1 = new DImage();

        /// <summary>
        /// image 2
        /// </summary>
        private DImage image2 = new DImage();

        /// <summary>
        /// opeation selected in operation combox
        /// </summary>
        private CmbValues operselected = CmbValues.Non;

        /// <summary>
        /// trak bar sum value
        /// </summary>
        private double trakBarSum = 0;

        /// <summary>
        /// image result
        /// </summary>
        private ImageStructure[,] result;

        /// <summary>
        /// run operation on image
        /// </summary>
        private bool runOPeration = false;

        /// <summary>
        /// Initializes a new instance of the <see cref="CalculationForm"/> class.
        /// </summary>
        public CalculationForm()
        {
            this.InitializeComponent();
            try
            {
                if (Main.ImageList.Count == 0)
                {
                    goto jumb;
                }

                foreach (DImage img in Main.ImageList)
                {
                    this.cmbFirstImage.Items.Add(img.Name);
                    this.cmbSecondImage.Items.Add(img.Name);
                }

                this.cmbFirstImage.SelectedIndex = 0;
                if (Main.ImageList.Count > 1)
                {
                    this.cmbSecondImage.SelectedIndex = 1;
                }
                else
                {
                    this.cmbSecondImage.SelectedIndex = 0;
                }

                this.image1.ImageStructArray = ResizeImage.BicubicResize(this.pcbFirstImage.Width, this.pcbFirstImage.Height, Main.ImageList[this.cmbFirstImage.SelectedIndex].ImageStructArray, 2);
                this.pcbFirstImage.Image = Operations.DisplayMatrix(this.image1.ImageStructArray);
                this.image2.ImageStructArray = ResizeImage.BicubicResize(this.pcbSecondImage.Width, this.pcbSecondImage.Height, Main.ImageList[this.cmbSecondImage.SelectedIndex].ImageStructArray, 2);
                this.pcbSecondImage.Image = Operations.DisplayMatrix(this.image2.ImageStructArray);

            jumb:
                this.cmbOperation.Items.Add(CmbValues.And.ToString());
                this.cmbOperation.Items.Add(CmbValues.Sum.ToString());
                this.cmbOperation.Items.Add(CmbValues.Sub.ToString());
                this.cmbOperation.Items.Add(CmbValues.Or.ToString());
                this.cmbOperation.Items.Add(CmbValues.Product.ToString());
                this.cmbOperation.Items.Add(CmbValues.Xor.ToString());
                this.cmbOperation.Items.Add(CmbValues.NAnd.ToString());
                this.cmbOperation.Items.Add(CmbValues.Nor.ToString());
                this.cmbOperation.Items.Add(CmbValues.Xnor.ToString());
                this.cmbOperation.Items.Add(CmbValues.Implies.ToString());
                this.cmbOperation.Items.Add(CmbValues.Image1IffImage2.ToString());
                this.trackBar1.Value = 1;
                this.trackBar1.Visible = false;
                this.result = new ImageStructure[this.pcbNewImage.Height, this.pcbNewImage.Width];
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        /// <summary>
        /// Handles the Load event of the CalculationForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void CalculationForm_Load(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Handles the Click event of the btnCancel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BtnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the cmbFirstImage control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void CmbFirstImage_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                this.image1.ImageStructArray = ResizeImage.BicubicResize(this.pcbFirstImage.Width, this.pcbFirstImage.Height, Main.ImageList[this.cmbFirstImage.SelectedIndex].ImageStructArray, 2);
                this.pcbFirstImage.Image = Operations.DisplayMatrix(this.image1.ImageStructArray);
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the cmbSecondImage control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void CmbSecondImage_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.image2.ImageStructArray = ResizeImage.BicubicResize(this.pcbSecondImage.Width, this.pcbSecondImage.Height, Main.ImageList[this.cmbSecondImage.SelectedIndex].ImageStructArray, 2);
            this.pcbSecondImage.Image = Operations.DisplayMatrix(this.image2.ImageStructArray);
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the cmbOperation control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void CmbOperation_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                this.trackBar1.Visible = false;
                this.runOPeration = true;
                switch (this.cmbOperation.SelectedIndex)
                {
                    case 0:
                        this.operselected = CmbValues.And;
                        this.result = CalcOperation.AndIamges(this.image1.ImageStructArray, this.image2.ImageStructArray);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "AND";
                        break;
                    case 1:
                        this.operselected = CmbValues.Sum;
                        this.trackBar1.Visible = true;
                        this.result = CalcOperation.SumIamges(this.image1.ImageStructArray, this.image2.ImageStructArray, this.trakBarSum);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "Sum";
                        break;
                    case 2:
                        this.operselected = CmbValues.Sub;
                        this.result = CalcOperation.SubIamgesOld(this.image1.ImageStructArray, this.image2.ImageStructArray);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "Sub";
                        break;
                    case 3:
                        this.operselected = CmbValues.Or;
                        this.result = CalcOperation.OrIamges(this.image1.ImageStructArray, this.image2.ImageStructArray);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "OR";
                        break;
                    case 4:
                        this.operselected = CmbValues.Product;
                        this.result = CalcOperation.PrudectIamges(this.image1.ImageStructArray, this.image2.ImageStructArray);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "Product";
                        break;
                    case 5:
                        this.operselected = CmbValues.Xor;
                        this.result = CalcOperation.XorImages(this.image1.ImageStructArray, this.image2.ImageStructArray);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "XOR";
                        break;
                    case 6:
                        this.operselected = CmbValues.NAnd;
                        this.result = CalcOperation.NAndImges(this.image1.ImageStructArray, this.image2.ImageStructArray);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "NAND";
                        break;
                    case 7:
                        this.operselected = CmbValues.Nor;
                        this.result = CalcOperation.NOrImges(this.image1.ImageStructArray, this.image2.ImageStructArray);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "NOR";
                        break;
                    case 8:
                        this.operselected = CmbValues.Xnor;
                        this.result = CalcOperation.XNorImages(this.image1.ImageStructArray, this.image2.ImageStructArray);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "XNOR";
                        break;
                    case 9:
                        this.operselected = CmbValues.Implies;
                        this.result = CalcOperation.ImpliesImages(this.image1.ImageStructArray, this.image2.ImageStructArray);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "Implies";
                        break;
                    case 10:
                        this.operselected = CmbValues.Image1IffImage2;
                        this.result = CalcOperation.Image1IffImage2(this.image1.ImageStructArray, this.image2.ImageStructArray);
                        this.pcbNewImage.Image = Operations.DisplayMatrix(this.result);
                        Main.OperationName = "Equivelance";
                        break;
                    default:
                        this.operselected = CmbValues.Non;
                        this.trackBar1.Visible = false;
                        break;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        /// <summary>
        /// Handles the Click event of the btnOk control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BtnOk_Click(object sender, EventArgs e)
        {
            if (this.runOPeration)
            {
               // this.result = ResizeImage.BicubicResize(Main.ImageList[Main.CurrImage].Width, Main.ImageList[Main.CurrImage].Height, this.result, 2);
                //Main.ImageList[this.cmbFirstImage.SelectedIndex].UpdateImage( this.result);

                Main.ImageList[cmbFirstImage.SelectedIndex].UpdateImage(ResizeImage.BicubicResize(Main.ImageList[cmbFirstImage.SelectedIndex].Width, Main.ImageList[cmbFirstImage.SelectedIndex].Height, this.result, 2));
            }

            this.Close();
        }

        /// <summary>
        /// Handles the Scroll event of the trackBar1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void TrackBar1_Scroll(object sender, EventArgs e)
        {
            if (this.operselected == CmbValues.Sum)
            {
                this.trakBarSum = Convert.ToDouble((double)this.trackBar1.Value / 10);
                this.result = CalcOperation.SumIamges(this.image1.ImageStructArray, this.image2.ImageStructArray, this.trakBarSum);
                this.pcbNewImage.Image = Operations.DisplayMatrix(ResizeImage.BicubicResize(this.pcbNewImage.Width, this.pcbNewImage.Height, this.result, 2));
            }
        }
    }
}
